#include <linux/module.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/spinlock.h>


static irqreturn_t linus_irq(int irqid, void *v)
{
	printk("---> %d\n", irqid);

//	while(1);
	
	return IRQ_WAKE_THREAD;
}

static irqreturn_t linus_thread_irq(int irqid, void *v)
{
	printk("thread---> %d\n", irqid);

	while(1)
	{
		msleep(1000);
		break;
	}
	return IRQ_HANDLED;
}

static int gpio_probe(struct platform_device *pdev)
{
	struct device_node *child = NULL;
	int i = 0;
	
	printk("gpio probe %s\n", pdev->name ? : "null");

	struct gpio_desc *d = gpiod_get_index(&pdev->dev, "gpi", 0);
	printk("----> %p\n", d);
	
	struct device_node *pnode = of_find_node_by_path("/linus/child1");
	printk("find node by path  = %p\n", pnode);
	
	printk("%d gpios\n", of_gpio_named_count(pnode, "gpi-gpios"));


	for_each_child_of_node(pdev->dev.of_node, child)
	{
		int t = of_gpio_named_count(pnode, "gpi-gpios");
		int tt = 0;
//		of_get_gpio_flags(struct device_node * np, int index, enum of_gpio_flags * flags)
			
		for(; tt<t;tt++)
		{
//			printk("for each %d\n", of_get_named_gpio(child, "gpi-gpios", tt));
			unsigned int gpio = of_get_named_gpio(child, "gpi-gpios", tt);
			struct gpio_desc *d = gpio_to_desc(gpio);

			unsigned irq = gpiod_to_irq(d);
			
//			unsigned irq = gpio_to_irq(gpio);
			
			request_threaded_irq(irq, linus_irq, linus_thread_irq, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "linus", NULL);
		}
		
	}
	
	return 0;
}

static struct of_device_id gpio_keys_of_match[] = {
	{ .compatible = "linus,gpio", },
	{ },
};

static struct platform_driver gpio_keys_device_driver = {
	.probe		= gpio_probe,
	.driver		= {
		.name	= "linus",
		.owner	= THIS_MODULE,
//		.pm	= &gpio_keys_pm_ops,
		.of_match_table = of_match_ptr(gpio_keys_of_match),
	}
};

static int __init linus_gpio_init(void)
{
	return platform_driver_register(&gpio_keys_device_driver);
}

static void __exit linus_gpio_exit(void)
{
	platform_driver_unregister(&gpio_keys_device_driver);
}

late_initcall(linus_gpio_init);
module_exit(linus_gpio_exit);

MODULE_LICENSE("GPL");



